const moment = require('moment');

const JiraModel = require('../Models/JiraModel');
const jiraDbModel =require('../Models/jiraDbModel')

const TimeTool = require('../Tools/TimeTool');
const JiraTool = require('../Tools/JiraTool');

const Pool = require('../Tools/Pool');

const LogService = require('./LogService');
const _ = require('lodash');

class JiraService {

  /**
   * 返回Jira相关数据总览
   */
  async pandect() {
    let ret = await JiraModel.getJiraSql();

    if (ret.id) {
      delete ret.id;
    };
    return ret;
  };

  async SinglePandect(projectid) {
    let ret = await JiraModel.getSingleProjectTableSql(projectid)
    return ret
  }

  async QualityFactor() {

    let ret = await JiraModel.getQualityfactorTabelSql()

    return ret
  }

  async JiraDbModelEachM(year,projectid){
    let res= await jiraDbModel.JiraDbEachMonthBug(year,projectid)
    return res
  }

  async jiraDbModelAllM(year){
    let res =await jiraDbModel.JiraDbAllMonthBug(year)
    return res
  }
  

  /**
   * 从Jira服务器中获取数据，并保存到数据库
   */
  async run() {
    await savePandectToSql();
  };
  async runSingle() {
    await saveSingleProjectToSql();
  }

  


};



async function savePandectToSql() {

  let jiraData = {};
  LogService.info('Start');
  jiraData.projectNameAndId= await getProjectNameAndId();
  // LogService.info('jiraData.projectNameAndId=',jiraData.projectNameAndId)
  // LogService.info('projectNameAndId');

  jiraData.bugTotal = await getBugTotal();
  // LogService.info('jiraData.bugTotal=',jiraData.bugTotal)
  // LogService.info('BugTotal');

  jiraData.bugNumWeekGrowth = await getBugNumWeekGrowth();
  //LogService.info('BugNumWeekGrowth');

  jiraData.bugNumDayGrowth = await getBugNumDayGrowth();
 // LogService.info('BugNumDayGrowth');

  jiraData.bugDayAverage = await getBugDayAverage(jiraData.bugTotal);
 // LogService.info('BugDayAverage');

  jiraData.bugMonthDetail = await getBugMonthDetail();
 // LogService.info('BugMouthDetail');

  jiraData.bugMonthTotal = await getBugMonthTotal(jiraData.bugMonthDetail);
  //LogService.info('BugMonthTotal');

  jiraData.bugMonthMax = await getBugMonthMax(jiraData.bugMonthDetail);
 // LogService.info('BugMonthMax');

  jiraData.bugHandingRate = await getBugHandingRate(jiraData.bugTotal);
 // LogService.info('BugHandingRate');

  jiraData.bugHandingWeekGrowth = await getBugHandingWeekGrowth();
  //LogService.info('BugHandingWeekGrowth');

  jiraData.bugHandingDayGrowth = await getBugHandingDayGrowth();
  //LogService.info('BugHandingDayGrowth');

  jiraData.bugModel = await getBugModle();
 // LogService.info('BugModel');

  jiraData.severityCount = await getBugSeverityCount();
  LogService.info('BugSeverityCount');

  jiraData.defectTypeCount = await getBugDefectTypeCount();
  LogService.info('BugDefectTypeCount');

  jiraData.leakTestCount = await getBugLeakTestCount();
  LogService.info('BugLeakTestCount');

  jiraData.bugProjectTotal = await getBugProjectTotal();
 // LogService.info('BugProjectTotal');

  jiraData.bugProjectHandUp = await getBugProjectHandUp(jiraData.bugHandingRate);
 // LogService.info('BugProjectHandUp');

  jiraData.bugProjectTrend = await getBugProjectTrend();
  //LogService.info('BugProjectTrend');
 
  jiraData.bugLeverProjectOlder = await getBugProjectTotalLeve();
 // LogService.info('bugLeverProjectOlder');

  jiraData.bugAllMonthTotalBug = await JiraModel.getBugAllMonthTotalBug();

  await JiraModel.saveToSql(jiraData);
  LogService.info('jiraData操作保存', jiraData)
  LogService.info('Saving');
};

/*
 根据ID 更新数据
*/
async function saveSingleProjectToSql(){

      
 let AllProjectObject = await JiraModel.getProjectById();
 
  LogService.info('获取所有项目信息完成',AllProjectObject)
 let idArry =await JiraModel.projectIdPushArray(AllProjectObject);
 

  LogService.info('过滤出ID数组准备完成',idArry)
   await JiraModel.saveSingleBugToSql(idArry);
   LogService.info('根据ID数组插入对应项目各个维度数据完成',idArry)
   await JiraModel.saveQualityfactorToSql(idArry)
  LogService.info('质量系数维度计算完成',idArry)
  
}



async function getBugTotal() {
  let res = await JiraModel.getBugByJql();
  let ret = res.total;
  return ret;
};

async function getProjectSingleTotal() {
  let res = await JiraModel.getSingleBugByJql();
  let ret = res.total;
  return ret;
};

async function getBugNumWeekGrowth() {
  let ret = 0;
  let oneWeek = await JiraModel.getBugByJql({ jql: 'created >= -1w' });
  let twoWeek = await JiraModel.getBugByJql({ jql: 'created >= -2w' });
  let prev = twoWeek.total - oneWeek.total;
  let next = oneWeek.total;
  if (prev !== 0) {
    ret = (((next - prev) / prev) * 100).toFixed(1);
    //console.log('!!!next',next,'prev',prev,'(next - prev) ',(next - prev) ,'/',prev,'ret',ret)
  };
  return ret;
};



async function getBugNumDayGrowth() {
  let ret = 0;
  let oneDay = await JiraModel.getBugByJql({ jql: 'created >= -1d' });
  let twoDay = await JiraModel.getBugByJql({ jql: 'created >= -2d' });
  let prev = twoDay.total - oneDay.total;
  let next = oneDay.total;
  if (prev !== 0) {
    ret = (((next - prev) / prev) * 100).toFixed(1);
    //console.log('!!!next2',next,'prev2',prev,'(next - prev) ',(next - prev) ,'/',prev,'ret2',ret)
  };
  return ret;
};

async function getBugDayAverage(data) {
  let days = TimeTool.getDays('2016/01/15');
  let ret = data / days;
  return ret;
};

async function getBugMonthTotal(data) {
  let sum = 0;
  for (let i in data) {
    sum += data[i].y;
  };
  return sum;
};

async function getBugMonthDetail() {
  let ret = [];
  let now = new Date().getTime();
  for (let i = 0; i < 30; i++) {
    let nowDate = TimeTool.getDate(29 - i);
    let nextDate = TimeTool.getDate(28 - i);
    let res = await JiraModel.getBugByJql({ jql: `created >= ${nowDate} AND created <= ${nextDate}` });
    ret.push({
      x: nowDate,
      y: res.total
    });
  };
  return ret;
};

async function getBugMonthMax(data) {
  let max = 0;
  for (let i in data) {
    if (data[i].y > max) {
      max = data[i].y;
    };
  };
  return max;
};

async function getBugHandingRate(data) {

  let ret = 0;
  let res = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7' })
  if (data !== 0) {

    ret = (res.total / data * 100).toFixed(1);

  }
  return ret;
}

async function getBugHandingWeekGrowth() {
  let ret = 0;
  let oneWeek = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -1w' });
  let twoWeek = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -2w' });
  let prev = twoWeek.total - oneWeek.total;
  let next = oneWeek.total;
  if (prev !== 0) {
    ret = ((next - prev) / prev * 100).toFixed(1);

  };
  return ret;
}

async function getBugHandingDayGrowth() {
  let ret = 0;
  let oneDay = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -1d' });
  let twoDay = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -2d' });
  let prev = twoDay.total - oneDay.total;
  let next = oneDay.total;
  if (prev !== 0) {
    ret = ((next - prev) / prev * 100).toFixed(1);
  };
  return ret;
}

async function getProjectNameAndId() {

  let projArray = [];
  let projects = await JiraModel.getProjectById();
  for (let i of projects) {

    let { id, name } = i;
    projArray.push(
      {
        projectid: id,
        projectname: name
      }
    )
  }

  return projArray;

}


async function getBugModle() {

  let projArray = [];
  let projects = await JiraModel.getProjectById();
  //console.log('11',projects)

  for (let i of projects) {
    let { id, key, name } = i;
    let components = await getComponents(id, key);
    projArray.push({
      projectName: name,
      data: components,
    });
  };
  let ret = getAllProject(projArray);
  return ret;
};

/**
 * 获取各项目“严重程度”数量统计
 * 格式：[{ 
 *  pid: 11106, //项目id
    pname: 'mBlockApp', //项目名称
    general: 399, //严重程度：一般
    critical: 120, //严重程度：严重
    suggest: 3, //严重程度：建议
    prompt: 37, //严重程度：提示
    fatal: 8, //严重程度：致命
    highLevelCount: 128, // 致命和严重的总和，在默认严重程度排名中使用
    total: bug总数  
  } ],...]
 */
async function getBugSeverityCount() {
  let selectResult =await JiraModel.getCountByCustomField("严重程度");
  let extraProject = await JiraTool.getExtraProjectArr();

  let severityCount = []
  let allProjectCount = 0;
  let allProjectHighLevelCount = 0;
  let allFatal = 0;
  let allCritical = 0;
  let allGeneral = 0;
  let allPrompt = 0;
  let allSuggest = 0;
  _.forEach(extraProject, pid => {
    let filterResult = _.filter(selectResult, (d) => {
      return d.pid == pid;
    });
    if (filterResult.length > 0) {
      let result = { pid: filterResult[0].pid, pname: filterResult[0].pname };
      _.forEach(filterResult, (fr) => {
        let keys = ["致命", "严重", "一般", "提示", "建议"];
        let keyTranslate = ["fatal", "critical", "general", "prompt", "suggest"];
        let key = keyTranslate[_.indexOf(keys, fr.customValue)];
        let value = fr.customValueCount;
        allProjectCount += value;
        if(key == "fatal" || key == "critical" ){
          allProjectHighLevelCount += value;
        }
        _.merge(result, { [key]: value });
      })
      let seriousNum = 0;
      let fatalNum = 0;
      let generalNum = 0;
      let promptNum = 0;
      let suggestNum = 0;
      if (result.fatal) {
        fatalNum = result.fatal;
        allFatal +=result.fatal;
      }
      if (result.critical) {
        seriousNum = result.critical;
        allCritical += result.critical;
      }
      if (result.general) {
        generalNum = result.general;
        allGeneral += result.general;
      }
      if (result.prompt) {
        promptNum = result.prompt;
        allPrompt += result.prompt;
      }
      if (result.suggest) {
        suggestNum = result.suggest;
        allSuggest += result.suggest;
      }
      _.merge(result, {highLevelCount: seriousNum+fatalNum, total: seriousNum+fatalNum+generalNum+promptNum+suggestNum})
      severityCount.push(result);
    }
  });
  
  severityCount.push({pid:0, pname:"全部项目", highLevelCount: allProjectHighLevelCount, total:allProjectCount, allFatal, allCritical, allGeneral, allPrompt, allSuggest })
  return severityCount;
}

/**
 * 获取各项目“缺陷类型”数量统计
 */
async function getBugDefectTypeCount() {
  let selectResult =await JiraModel.getCountByCustomField("缺陷类型");
  let extraProject = await JiraTool.getExtraProjectArr();

  let defectTypeCount = []

  _.forEach(extraProject, pid => {
    let filterResult = _.filter(selectResult, (d) => {
      return d.pid == pid;
    });
    if (filterResult.length > 0) {
      let result = { pid: filterResult[0].pid, pname: filterResult[0].pname };
      _.forEach(filterResult, (fr) => {
        let key = fr.customValue;
        let value = fr.customValueCount;
        _.merge(result, { [key]: value });
      })
      defectTypeCount.push(result);
    }
  });

  return defectTypeCount;
}

/**
 * 获取各项目“漏测率”统计
 */
async function getBugLeakTestCount() {
  let selectResult =await JiraModel.getCountByCustomField("发现阶段");
  let extraProject = await JiraTool.getExtraProjectArr();

  let leakTestCount = []

  _.forEach(extraProject, pid => {
    let filterResult = _.filter(selectResult, (d) => {
      return d.pid == pid;
    });
    let total = 0;
    let leak = 0;
    if (filterResult.length > 0) {
      let result = { pid: filterResult[0].pid, pname: filterResult[0].pname };
      _.forEach(filterResult, (fr) => {
        let key = fr.customValue;
        let value = fr.customValueCount;
        total += fr.customValueCount;
        if(key == "用户反馈"){
          leak = value;
        }
        // _.merge(result, { [key]: value });
      })
      let leakRate = total == 0 || leak == 0 ? 0 : leak / total;
      _.merge(result, {total, leakCount:leak, leakRate,  })
      leakTestCount.push(result);
    }
  });
  return leakTestCount;  
}



function getAllProject(arr) {
  let allData = [];
  let rData = [];
  let ret = arr;
  for (let i in arr) {
    if (arr[i].data) {
      for (let j in arr[i].data) {
        allData.push(arr[i].data[j])
      };
    };
  };
  let retData = JiraTool.sortByKey(allData, 'count');
  for (let i in retData) {
    const item = retData[i]
    rData.push({
      index: parseInt(i) + 1,
      model: item.model,
      count: item.count,
      growth: item.growth,
    })
  };
  ret.unshift({ projectName: '全部项目', data: rData });
  return ret;
}



// 具体项目的Components 模块
async function getComponents(projectId, projectKey) {
  let ret = [];
  let filterIDParms = await JiraTool.filterIDParms(projectId)
 // console.log('22',filterIDParms)
  
  let { components } = await JiraModel.getProjectByIdparma(filterIDParms);

  if (components) {
    for (let j of components) {
      let { id, name } = j;
     // console.log('333id',id,'name',name)
      let component = await JiraModel.getBugByJql({ jql: `project = ${projectKey} AND component = ${id}` });
    //  console.log('444',component)
      let count = component.total;
      let growth = await getVersionGrowth(projectId, projectKey, id);
      ret.push({
        index: 0,
        model: name,
        count,
        growth,
      });
    };
    ret = JiraTool.sortByKey(ret, 'count');
    for (let a in ret) {
      ret[a].index = parseInt(a) + 1;
    }
  };
  return ret;
};

async function getVersionGrowth(projectId, projectKey, componentId) {
  let ret = 0;
  let versions = await JiraModel.getProjectVersionsById(projectId);
  if (versions && versions.length > 1) {
    let latestVersion = versions[versions.length - 1].id;
    let prevVersion = versions[versions.length - 2].id;
    let latestJql = `project = ${projectKey} AND affectedVersion = ${latestVersion} AND component = ${componentId}`;
    let prevJql = `project = ${projectKey} AND affectedVersion = ${prevVersion} AND component = ${componentId}`;
    let latest = await JiraModel.getBugByJql({ jql: latestJql });
    let prev = await JiraModel.getBugByJql({ jql: prevJql });
    if (prev.total !== 0) {
      ret = ((latest.total - prev.total) / prev.total * 10).toFixed(1);
    };
  };
  return ret;
};
//  遍历udo个ID
async function getBugProjectTotal() {

  let ret = [];
  let projects = await JiraModel.getProjectById();

  for (let i of projects) {
    let { id, name } = i;
   // console.log(`id:${id},name:${name}`)
    let projectBug = await JiraModel.getBugByJql({ jql: `project = ${id}` }); // 传递Jql对象 
    let { total } = projectBug;
    ret.push({ x: name, y: total });
  };
  ret = JiraTool.sortByKey(ret, 'y')

  return ret;
};


// 拿到ID 遍历所有项目ID
async function getBugProjectTotalLeve() {

  let ret = [];
  let proid = await JiraModel.getProjectIdLeve()
  for (let i of proid) {
    let { id, name } = i;
    let idTotal = await JiraModel.getBugLever(id);
    ret.push({ name: name, idTotal: idTotal })
  }
  let sortret = JiraTool.setarry(ret)

  return sortret;


}



async function getBugProjectHandUp(rate) {
  let ret = [];
  let projects = await JiraModel.getProjectById();
  for (let i in projects) {
    let handingRate = 0;
    let { id, name } = projects[i];
    let projectBug = await JiraModel.getBugByJql({ jql: `project = ${id}` });
    let { total } = projectBug;
    let projectHandUp = await JiraModel.getBugByJql({ jql: `project = ${id} AND status = %e6%8c%82%e8%b5%b7` });
    if (total !== 0) {
      handingRate = (projectHandUp.total / total * 100).toFixed(1);
    };
    ret.push({ projectName: name, handingRate });
  };
  ret.unshift({ projectName: '全部项目', handingRate: rate });
  return ret;
};

async function getBugProjectTrend() {
  let ret = [];
  let projects = await JiraModel.getProjectById();
  for (let i in projects) {
    let handingRate = 0;
    let { id, name } = projects[i];
    let projectBug = await JiraModel.getBugByJql({ jql: `project = ${id}` });
    ret.push({ projectId: id, projectName: name, data: [] });
  };
  await setProjectData(ret);
  await setAllProlectData(ret);
  return ret;
};

async function setAllProlectData(arr) {
  let now = new Date().getTime();
  arr.unshift({ projectName: '全部项目', data: [] });
  for (let i = 0; i < 30; i++) {
    let nowDate = TimeTool.getDate(29 - i);
    let nextDate = TimeTool.getDate(28 - i);
    let newBug = await JiraModel.getBugByJql({
      jql: `created >= ${nowDate} AND created <= ${nextDate}`
    });
    let fixBug = await JiraModel.getBugByJql({
      jql: `status in (%e5%b7%b2%e8%a7%a3%e5%86%b3, %e9%97%ae%e9%a2%98%e5%85%b3%e9%97%ad)
        AND updated >= ${nowDate} AND updated <= ${nextDate}`
    });
    let handupBug = await JiraModel.getBugByJql({
      jql: `status = %e6%8c%82%e8%b5%b7 AND updated >= ${nowDate} AND updated <= ${nextDate}`
    });
    arr[0].data.push({
      x: now - (1000 * 60 * 60 * 24 * (29 - i)),
      y1: newBug.total,
      y2: fixBug.total,
      y3: handupBug.total
    });
  };
};

async function setProjectData(projects) {
  let now = new Date().getTime();
  for (let k in projects) {
    for (let i = 0; i < 30; i++) {
      let nowDate = TimeTool.getDate(29 - i);
      let nextDate = TimeTool.getDate(28 - i);
      let newBug = await JiraModel.getBugByJql({
        jql: `project = ${projects[k].projectId} AND created >= ${nowDate} AND created <= ${nextDate}`
      });
      let fixBug = await JiraModel.getBugByJql({
        jql: `project = ${projects[k].projectId} AND status in (%e5%b7%b2%e8%a7%a3%e5%86%b3, %e9%97%ae%e9%a2%98%e5%85%b3%e9%97%ad)
          AND updated >= ${nowDate} AND updated <= ${nextDate}`
      });
      let handupBug = await JiraModel.getBugByJql({
        jql: `project = ${projects[k].projectId} AND status = %e6%8c%82%e8%b5%b7 AND updated >= ${nowDate} AND updated <= ${nextDate}`
      });
      projects[k].data.push({
        x: now - (1000 * 60 * 60 * 24 * (29 - i)),
        y1: newBug.total,
        y2: fixBug.total,
        y3: handupBug.total
      });
    };
  };
};

module.exports = new JiraService();
// getBugSeverityCount().then(data => {
//   console.log(data);
// })